{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-align: center\"><a href=\"index.ipynb\">LAMMPS Python Tutorials</a></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Example 1: Using LAMMPS with Python"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Author: [Richard Berger](mailto:richard.berger@outlook.com)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The LAMMPS Python package enables calling the LAMMPS C library API."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Prerequisites\n",
    "\n",
    "Before running this example, make sure your Python environment can find the LAMMPS shared library (`liblammps.so`) and the LAMMPS Python package is installed. If you followed the [README](README.md) in this folder, this should already be the case. You can also find more information about how to compile LAMMPS and install the LAMMPS Python package in the [LAMMPS manual](https://docs.lammps.org/Python_install.html). There is also a dedicated [LAMMPS Python HowTo](https://docs.lammps.org/Howto_python.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Creating a new simulation\n",
    "\n",
    "Once the LAMMPS shared library and the LAMMPS Python package are installed, you can create a new LAMMMPS instance in your Python interpreter as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from lammps import lammps\n",
    "L = lammps()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the `lammps` class you can write LAMMPS simulations similar to the input script language. Take the following LAMMPS input script:\n",
    "\n",
    "```lammps\n",
    "# 3d Lennard-Jones melt\n",
    "\n",
    "units        lj\n",
    "atom_style   atomic\n",
    "\n",
    "lattice      fcc 0.8442\n",
    "region       box block 0 4 0 4 0 4\n",
    "create_box   1 box\n",
    "create_atoms 1 box\n",
    "mass         1 1.0\n",
    "\n",
    "velocity     all create 1.44 87287 loop geom\n",
    "\n",
    "pair_style   lj/cut 2.5\n",
    "pair_coeff   1 1 1.0 1.0 2.5\n",
    "\n",
    "neighbor     0.3 bin\n",
    "neigh_modify delay 0 every 20 check no\n",
    "\n",
    "fix          1 all nve\n",
    "\n",
    "thermo       50\n",
    "```\n",
    "The equivalent can be written in Python:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3d Lennard-Jones melt\n",
    "\n",
    "L.cmd.units(\"lj\")\n",
    "L.cmd.atom_style(\"atomic\")\n",
    "\n",
    "L.cmd.lattice(\"fcc\", 0.8442)\n",
    "L.cmd.region(\"box\", \"block\", 0, 4, 0, 4, 0, 4)\n",
    "L.cmd.create_box(1, \"box\")\n",
    "L.cmd.create_atoms(1, \"box\")\n",
    "L.cmd.mass(1, 1.0)\n",
    "\n",
    "L.cmd.velocity(\"all\", \"create\", 1.44, 87287, \"loop geom\")\n",
    "\n",
    "L.cmd.pair_style(\"lj/cut\", 2.5)\n",
    "L.cmd.pair_coeff(1, 1, 1.0, 1.0, 2.5)\n",
    "\n",
    "L.cmd.neighbor(0.3, \"bin\")\n",
    "L.cmd.neigh_modify(\"delay\", 0, \"every\", 20, \"check no\")\n",
    "\n",
    "L.cmd.fix(\"1\", \"all\", \"nve\")\n",
    "\n",
    "L.cmd.thermo(50)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Some LAMMPS commands will produce output that will be visible in the notebook. However, due to buffering, it might not be shown right away. Use the `flush_buffers` method to see all the output that has been written so far."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "L.flush_buffers()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "An alternative to this is to enable auto flushing after each command by setting `cmd.auto_flush` to `True`. Each command will then call `flush_buffers()` automatically."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "L.cmd.auto_flush = True\n",
    "L.cmd.info(\"system\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In many cases the LAMMPS output will become excessive, which is why you may want to suppress it. For this purpose we provide a IPython extension in the `lammps.ipython` package. To load the extension, add a code cell with the following content:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext lammps.ipython"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once the extension is loaded you have access to the `%%capture_lammps_output` magic. In its simplest form it can be used to supress LAMMPS output:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture_lammps_output\n",
    "L.cmd.info(\"system\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also use the same `%%capture_lammps_output` magic to store the output in a variable by providing a variable name:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture_lammps_output out\n",
    "L.cmd.info(\"system\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this case we are storing the output in a `out` variable. Note the output is only available after the cell has been executed, not within the same cell."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(out)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualizing the initial state\n",
    "\n",
    "The `lammps` class also has an `ipython` attribute which provides some basic visualization capabilities in IPython Jupyter notebooks. E.g., you can visualize the current simulation state with the [image](https://docs.lammps.org/Python_module.html#lammps.ipython_wrapper.image) command. Here we use it to create an image of the initial state of the system."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "L.ipython.image()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Running simulations\n",
    "\n",
    "Use the `run` command to start the simulation. It will print the output of the simulation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "L.cmd.run(250)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Visualizing the system will now show us how the atoms have moved."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "L.ipython.image(zoom=1.0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "This covered the basics of creating an instance of LAMMPS from Python, passing commands to LAMMPS and potentially supressing or capturing its output, and visualizing the system. In the [following tutorial](thermo.ipynb) we will look at how to process thermodynamic output from LAMMPS.\n",
    "\n",
    "<div style=\"text-align:right\"><a href=\"thermo.ipynb\">Next</a>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
